package com.inspur.edp.common.type.extension;

import com.inspur.edp.common.expr.parser.DSLTypeBuilder;
import com.inspur.edp.common.type.Type;
import com.inspur.edp.common.type.TypeRefer;
import com.inspur.edp.common.type.deserializer.BasicTypeDeserializer;
import com.inspur.edp.common.type.deserializer.DefaultListDeserializer;
import com.inspur.edp.common.type.deserializer.DefaultObjectDeserializer;
import com.inspur.edp.common.type.deserializer.TypeDeserializer;
import com.inspur.edp.common.type.spi.TypeResourceProvider;
import com.inspur.edp.common.type.utils.JsonSerializeUtil;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author lizhaorui
 * @date 2025/9/26
 * @description
 */

public class DefaultTypeResourceProvider implements TypeResourceProvider {

    private static final String KIND = "default";

    private static final ConcurrentHashMap<String, TypeDeserializer> deserializerMap = new ConcurrentHashMap<>();

    private static final ConcurrentHashMap<String, TypeDeserializer> listDeserializerMap = new ConcurrentHashMap<>();

    private static ConcurrentHashMap<String, String> TYPE_DSL_MAP = new ConcurrentHashMap();

    private static final boolean INIT = false;

    @Override
    public Type getType(String typeId) {
        String dsl = this.getContent(typeId);
        DSLTypeBuilder builder = new DSLTypeBuilder();
        Type type = builder.build(typeId, dsl);
        type.setSource(KIND);
        type.setTypeId(typeId);
        return type;
    }

    @Override
    public String getUrl(String typeId) {
        return typeId;
    }

    @Override
    public TypeDeserializer getDeserializer(TypeRefer typeRefer) {
        if (typeRefer.isList()) {
            return this.getListDeserializer(typeRefer);
        } else {
            return this.getObjectDeserializer(typeRefer.getTypeId());
        }
    }

    @Override
    public List<TypeRefer> getTypesByBizId(String bizId) {
        return this.getTypeRefersByBizTypeId(bizId);
    }

    @Override
    public String getNavigationKind() {
        return TypeResourceProvider.BIZ_TYPE_NAV;
    }

    private TypeDeserializer getListDeserializer(TypeRefer typeRefer) {
        String typeId = typeRefer.getGenericType(0).getTypeId();
        TypeDeserializer deserializer = listDeserializerMap.get(typeId);
        if (deserializer != null) {
            return deserializer;
        } else {
            synchronized (DefaultTypeResourceProvider.class) {
                if (!listDeserializerMap.containsKey(typeId)) {
                    TypeDeserializer objectDeserializer = this.getObjectDeserializer(typeId);
                    deserializer = new DefaultListDeserializer(objectDeserializer);
                    listDeserializerMap.put(typeId, deserializer);
                } else {
                    deserializer = listDeserializerMap.get(typeId);
                }
            }
            return deserializer;
        }
    }

    private TypeDeserializer getObjectDeserializer(String typeId) {
        TypeDeserializer deserializer = deserializerMap.get(typeId);
        if (deserializer != null) {
            return deserializer;
        } else {
            synchronized (DefaultTypeResourceProvider.class) {
                if (!deserializerMap.containsKey(typeId)) {
                    Type type = this.getType(typeId);
                    String typeCode = type.getTypeOptCode();
                    if (!typeCode.contains(".")) {
                        if (typeCode.equalsIgnoreCase("double")) {
                            deserializer = new BasicTypeDeserializer.DoubleDeserializer();
                        } else if (typeCode.equalsIgnoreCase("int")) {
                            deserializer = new BasicTypeDeserializer.IntegerDeserializer();
                        } else if (typeCode.equalsIgnoreCase("boolean")) {
                            deserializer = new BasicTypeDeserializer.BooleanDeserializer();
                        } else if (typeCode.equalsIgnoreCase("long")) {
                            deserializer = new BasicTypeDeserializer.LongDeserializer();
                        } else {
                            typeCode = "java.lang." + typeCode;
                            deserializer = new DefaultObjectDeserializer(typeCode);
                        }
                    } else {
                        deserializer = new DefaultObjectDeserializer(typeCode);
                    }
                    deserializerMap.put(typeId, deserializer);
                } else {
                    deserializer = deserializerMap.get(typeId);
                }
                return deserializer;
            }
        }
    }

    @Override
    public String getKind() {
        return KIND;
    }

    private String getContent(String url) {
        String dir = ResourceConfig.TYPE_DSL_DIR;
        if (dir == null || dir.length() == 0) {
            throw new RuntimeException("please set type dsl dir");
        }
        File file = Paths.get(dir, url + ".dsl").toFile();
        if (!file.exists()) {
            throw new RuntimeException(String.format("file %s not exists。", Paths.get(dir, url + ".dsl").toString()));
        }
        try {
            List<String> contentLines = Files.readAllLines(Paths.get(dir, url + ".dsl"));
            StringBuilder stringBuilder = new StringBuilder();
            for (String str : contentLines) {
                stringBuilder.append("\n" + str);
            }
            return stringBuilder.toString();
        } catch (IOException e) {
            throw new RuntimeException("read file occur exception。");
        }
    }

    private List<TypeRefer> getTypeRefersByBizTypeId(String bizTypeId) {
        throw new RuntimeException();
    }

}
